package com.h2ospace.yeelight.controller;

import com.h2ospace.yeelight.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping(value = "/controller")
@Api(value = "灯光控制")
public class YeeLightController {

    @Value("${yeelight.port}")
    private String port;
    @Value("${yeelight.searchPort}")
    private String searchPort;
    @Value("${yeelight.searchIp}")
    private String searchIp;

    @RequestMapping(value = "/search", method = RequestMethod.GET)
    @ApiOperation(value = "查询Yeelight设备", notes = "searchTime 默认3000ms")
    public Result search(@RequestParam(value = "searchTime",defaultValue = "3000")String searchTime) {
        Result result = new Result();
        DatagramSocket detectSocket = null;
        List<String> resultList = new ArrayList<>();
        try {
            detectSocket = new DatagramSocket(Integer.parseInt(searchPort));
            String message = "M-SEARCH * HTTP/1.1\r\nMAN: \"ssdp:discover\"\r\nST: wifi_bulb\r\n";
            InetAddress hostAddress = InetAddress.getByName(searchIp);
            DatagramPacket out = new DatagramPacket(message.getBytes(), message.length(), hostAddress, Integer.parseInt(searchPort));
            detectSocket.setSoTimeout(Integer.parseInt(searchTime));
            detectSocket.send(out);
            while (true){
                //定义数据缓冲
                byte[] buf = new byte[1024];
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                //接受数据
                detectSocket.receive(packet);
                String received = new String(packet.getData(),"utf-8").substring(61,101);
                if(!resultList.contains(received)){
                    resultList.add(received);
                }
            }
        } catch (IOException e) {
            result.setCode(HttpStatus.REQUEST_TIMEOUT.toString());
            result.setMessage(e.getMessage());
            return result;
        } finally {
            detectSocket.close();
            result.setMessage(String.join(",",resultList));
            result.setCode(HttpStatus.OK.toString());
            return result;
        }
    }

    @RequestMapping(value = "/setPower_on", method = RequestMethod.POST)
    @ApiOperation(value = "开启灯光")
    public Result setPower(@RequestParam("ip") String ip) {
        Result result = new Result();
        String msg = "{ \"id\": " + (new Date()).getTime() + ", \"method\": \"set_power\", \"params\":[\"on\", \"smooth\", 500]}\r\n";
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            if (StringUtils.isEmpty(ip)) {
                result.setCode(HttpStatus.UNAUTHORIZED.toString());
                result.setMessage("ip Is Required");
                return result;
            }
            socket = new Socket(ip, Integer.parseInt(port));
            outputStream = socket.getOutputStream();
            outputStream.write(msg.getBytes());
            outputStream.flush();
            result.setCode(HttpStatus.OK.toString());
            result.setMessage(getResponseMessage(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @RequestMapping(value = "/setPower_off", method = RequestMethod.POST)
    @ApiOperation(value = "关闭灯光")
    public Result setPowerOff(@RequestParam("ip") String ip) {
        Result result = new Result();
        String msg = "{ \"id\": " + (new Date()).getTime() + ", \"method\": \"set_power\", \"params\":[\"off\"]}\r\n";
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            if (StringUtils.isEmpty(ip)) {
                result.setCode(HttpStatus.UNAUTHORIZED.toString());
                result.setMessage("ip Is Required");
                return result;
            }
            socket = new Socket(ip, Integer.parseInt(port));
            outputStream = socket.getOutputStream();
            outputStream.write(msg.getBytes());
            outputStream.flush();
            result.setCode(HttpStatus.OK.toString());
            result.setMessage(getResponseMessage(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @RequestMapping(value = "/setPower_toggle", method = RequestMethod.POST)
    @ApiOperation(value = "灯的状态切换")
    public Result setPowerToggle(@RequestParam("ip") String ip) {
        Result result = new Result();
        System.out.println(UUID.randomUUID());
        String msg = "{ \"id\": " + (new Date()).getTime() + ", \"method\": \"toggle\", \"params\":[]}\r\n";
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            if (StringUtils.isEmpty(ip)) {
                result.setCode(HttpStatus.UNAUTHORIZED.toString());
                result.setMessage("ip Is Required");
                return result;
            }
            socket = new Socket(ip, Integer.parseInt(port));
            outputStream = socket.getOutputStream();
            outputStream.write(msg.getBytes());
            outputStream.flush();
            result.setCode(HttpStatus.OK.toString());
            result.setMessage(getResponseMessage(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    @RequestMapping(value = "/set_bright", method = RequestMethod.POST)
    @ApiOperation(value = "设置灯的亮度")
    public Result setBright(@RequestParam("ip") String ip, @RequestParam("bright") String bright) {
        Result result = new Result();
        String msg = "{ \"id\": " + (new Date()).getTime() + ", \"method\": \"set_bright\", \"params\":[" + bright + "]}\r\n";
        Socket socket = null;
        OutputStream outputStream = null;
        try {
            if (StringUtils.isEmpty(ip)) {
                result.setCode(HttpStatus.UNAUTHORIZED.toString());
                result.setMessage("ip Is Required");
                return result;
            }
            if (StringUtils.isEmpty(bright)) {
                result.setCode(HttpStatus.UNAUTHORIZED.toString());
                result.setMessage("bright Is Required");
                return result;
            }
            socket = new Socket(ip, Integer.parseInt(port));
            outputStream = socket.getOutputStream();
            outputStream.write(msg.getBytes());
            outputStream.flush();
            result.setCode(HttpStatus.OK.toString());
            result.setMessage(getResponseMessage(socket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private String getResponseMessage(InputStream inputStream) {
        byte[] bytes = new byte[0];
        InputStream in = inputStream;
        try {
            bytes = new byte[1024];
            in.read(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return new String(bytes);
    }
}
